package com.edais.service.imp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.edais.dao.SpreadDao;
import com.edais.domain.AdSpreadCount;
import com.edais.service.SpreadService;

@Service

public class SpreadServiceImp implements SpreadService {
	private static final Log logger = LogFactory.getLog(SpreadServiceImp.class);
	
	@Autowired
	private SpreadDao spreadDao;

	/**
	 * 用户点击广告
	 * @param map
	 * @return
	 * @throws Exception 
	 */
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,readOnly=false)
	public void userClickAd(Map<String, String> map) throws Exception{
		AdSpreadCount adSpreadCount = new AdSpreadCount();
		
//		// ios7 以下版本取得WIFI MAC地址
//		String iosVer = map.get("iosVersion");
//		if (iosVer != null && iosVer.length() > 0) {
//			Integer verNo = Integer.valueOf(iosVer.substring(0, 1));
//			if (verNo < 7) {
//				adSpreadCount.setUdid(map.get("mac"));
//			}
//		}
		// WIFI MAC地址
		adSpreadCount.setUdid(map.get("mac"));
		// APP标识
		adSpreadCount.setAppId(map.get("appId"));
		// 用户的IDFA
		adSpreadCount.setIfa(map.get("idfa"));
		// 渠道
		adSpreadCount.setChannel(map.get("channel"));
		// 用户的OpenUDID
		adSpreadCount.setOpenUDID(map.get("openUDID"));
		// 当前点击广告用户的IP地址
		adSpreadCount.setClickIp(map.get("clickIp"));
		
		// 根据用户信息查询是否已点击过广告
		AdSpreadCount result = this.spreadDao.queryEquipmentInfoForClick(adSpreadCount);
		if (result == null) {    // 点击记录为空
			result = new AdSpreadCount();
			// APP标识
			result.setAppId(adSpreadCount.getAppId());
			// 带冒号的WIFI MAC地址
			result.setUdid(checkNull(adSpreadCount.getUdid()));
			// 用户的IDFA
			result.setIfa(checkNull(adSpreadCount.getIfa()));
			// 用户的OpenUDID
			result.setOpenUDID(checkNull(adSpreadCount.getOpenUDID()));
			// 当前点击广告用户的IP地址
			result.setClickIp(adSpreadCount.getClickIp());
			// 渠道
			result.setChannel(adSpreadCount.getChannel());
			// 是否已点击
			result.setIsClick("Y");
			// 是否已激活
			result.setIsActivate("N");
			// 是否已回调广告商
			result.setIsCallback("N");
			
			// 作成记录信息
			this.spreadDao.insertEquipmentInfo(result);
		} else {
			if ("Y".equals(adSpreadCount.getIsActivate())) {
				// 已激活用户
				logger.debug(">>>>>>>>>>>>>>>>>该设备已激活");
			} else if (this.checkClickTime(result.getClickTime()) <= 3) {
				// 有3天内的点击纪录
				logger.debug(">>>>>>>>>>>>>>>>>该设备已有三天内的点击纪录");
			} else {
				result.setClickIp(adSpreadCount.getClickIp());
				
				// 更新点击记录信息
				this.spreadDao.updateClickTime(result);
			}
		}
	}
	
	/**
	 * 用户激活App
	 * @param map
	 * @return
	 * @throws Exception 
	 */
	@Override
	@Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class,readOnly=false)
	public void userActivateApp(Map<String, String> map) throws Exception {
		AdSpreadCount adSpreadCount = new AdSpreadCount();
		
//		// ios7 以下版本取得WIFI MAC地址
//		String iosVer = map.get("iosVersion");
//		if (iosVer != null && iosVer.length() > 0) {
//			Integer verNo = Integer.valueOf(iosVer.substring(0, 1));
//			if (verNo < 7) {
//				adSpreadCount.setUdid(map.get("mac"));
//			}
//		}
		// WIFI MAC地址
		adSpreadCount.setUdid(map.get("mac"));
		// APP标识
		adSpreadCount.setAppId(map.get("appId"));
		// 用户的IDFA
		adSpreadCount.setIfa(map.get("idfa"));
		// app版本号
		adSpreadCount.setAppVersion(map.get("appVersion"));
		// 用户激活App时的IP地址
		adSpreadCount.setActIp(map.get("actIp"));
		
		// 查询用户的点击纪录
		AdSpreadCount result = this.spreadDao.queryEquipmentInfoForAct(adSpreadCount);
		if (result == null) {
			// 无记录
			logger.debug(">>>>>>>>>>>>>>>>>不是广告商推广用户");
		} else {
			// 激活时间
			result.setActTime(new Date());
			// 激活ip
			result.setActIp(adSpreadCount.getActIp());
			// app版本
			result.setAppVersion(adSpreadCount.getAppVersion());
			// 是否已激活
			result.setIsActivate("Y");
			
			// 检查激活时间是否超过3天
			Integer actDays = this.checkClickTime(result.getClickTime());
			if (actDays <= 3) {    // 3天以内
				// 生成回调URL
				String callbackURL = this.createDomobURL(result);
				
				// 中间变量，回调次数
				int cnt = 0;
				boolean flg = true;
				JSONObject jsonObj = new JSONObject();
				
				while (flg && cnt < 5) {
					cnt = cnt + 1;
					try {
						// 回调广告商
						String rtnStr = this.httpConnection(callbackURL);
						jsonObj = JSONObject.fromObject(rtnStr);
						// 回调成功
						if (jsonObj.getBoolean("success")) {
							flg = false;
						}
					} catch (Exception e) {
						logger.debug(">>>>>>>>>>>>>>>>>>>>>回调第三方广告商 异常：" + e.getCause());
					}
				}
				
				// 是否已回调
				result.setIsCallback("Y");
				// 回调URL
				result.setCallbackURL(callbackURL);
				// 回调次数
				result.setCallbackCount(String.valueOf(cnt));
				// 回调返回信息
				result.setReturnMessage(jsonObj.getString("message"));
				// 回调返回结果
				result.setCallbackResult(jsonObj.getString("success"));
				
				// 更新回调信息
				this.spreadDao.updateEquipmentInfo(result);
			} else {  // 激活大于3天
				// 未回调原因
				result.setNotCallbackReason("用户激活App，延迟： " + actDays + " 天。");
				
				// 更新
				this.spreadDao.updateEquipmentInfo(result);
			}
		}
		
	}

	/**
	 * 多盟回调URL作成
	 * @param map
	 * @return
	 * @throws Exception 
	 */
	private String createDomobURL(AdSpreadCount adSpreadCount) {
		StringBuffer callbackUrl = new StringBuffer();
		Properties properties = new Properties();
		
		try {
			// 加载推广配置文件
			properties = PropertiesLoaderUtils.loadAllProperties("spread.properties");
		} catch (IOException e) {
			logger.debug(">>>>>>>>>>>>>>>>>>>>>加载回调URL配置文件 异常：" + e.getCause());
		}
		
		// 多盟
		if ("DOMOB".equals(adSpreadCount.getChannel())) {
			String maStr = "";      // 中间变量，WIFI MAC地址MD5加密再转为大写
			String udidStr = "";    // 中间变量，WIFI MAC地址
			String oidStr = "";     // 中间变量，用户的OpenUDID
			
			callbackUrl.append(properties.getProperty("DOMOB_URL")).append("?");
			callbackUrl.append("appId=").append(adSpreadCount.getAppId()).append("&");
			
			/***********ios6激活异常***********/
//			if (StringUtils.isNotBlank(adSpreadCount.getUdid())) {
//				maStr = MD5.md5(adSpreadCount.getUdid());
//				udidStr = adSpreadCount.getUdid();
//
//				callbackUrl.append("udid=").append(udidStr).append("&");
//				callbackUrl.append("ma=").append(maStr).append("&");
//			}
//			
//			if (StringUtils.isNotBlank(adSpreadCount.getOpenUDID())) {
//				oidStr = adSpreadCount.getOpenUDID();
//
//				callbackUrl.append("oid=").append(oidStr).append("&");
//			}
			/***********ios6激活异常***********/
			
			callbackUrl.append("ifa=").append(adSpreadCount.getIfa()).append("&");
			callbackUrl.append("clktime=").append(adSpreadCount.getClickTime().getTime()).append("&");
			callbackUrl.append("acttime=").append(adSpreadCount.getActTime().getTime()).append("&");
			callbackUrl.append("clkip=").append(adSpreadCount.getClickIp()).append("&");
			/***********激活ip去掉***********/
//			callbackUrl.append("ip=").append(adSpreadCount.getActIp()).append("&");
			/***********激活ip去掉***********/
			callbackUrl.append("appVersion=").append(adSpreadCount.getAppVersion()).append("&");
			callbackUrl.append("returnFormat=").append("1").append("&");
			
			try {
				String sign = getDomobSign(adSpreadCount.getAppId(), udidStr, maStr, adSpreadCount.getIfa(), 
												oidStr, properties.getProperty("DOMOB_KEY"));

				callbackUrl.append("sign=").append(sign);
			} catch (NoSuchAlgorithmException e) {
				logger.debug(">>>>>>>>>>>>>生成多盟验证标签 异常：" + e.getCause());
				return "";
			}
			
		} else if ("WAPS".equals(adSpreadCount.getChannel())) {
			callbackUrl.append(properties.getProperty("WAPS_URL")).append("?");
			callbackUrl.append("app=").append(adSpreadCount.getAppId()).append("&");
			
			/***********ios6激活异常***********/
//			if (StringUtils.isNotBlank(adSpreadCount.getUdid())) {
//				callbackUrl.append("udid=").append(adSpreadCount.getUdid()).append("&");
//			}
//			
//			if (StringUtils.isNotBlank(adSpreadCount.getOpenUDID())) {
//				callbackUrl.append("openudid=").append(adSpreadCount.getOpenUDID()).append("&");
//			}
			/***********ios6激活异常***********/
			
			callbackUrl.append("idfa=").append(adSpreadCount.getIfa());
			
		} else if ("YOUMI".equals(adSpreadCount.getChannel())) {
			callbackUrl.append(properties.getProperty("YOUMI_URL")).append("?");
			callbackUrl.append("appId=").append(adSpreadCount.getAppId()).append("&");
			
			/***********ios6激活异常***********/
//			if (StringUtils.isNotBlank(adSpreadCount.getUdid())) {
//				callbackUrl.append("udid=").append(adSpreadCount.getUdid()).append("&");
//			}
//			
//			if (StringUtils.isNotBlank(adSpreadCount.getOpenUDID())) {
//				callbackUrl.append("oid=").append(adSpreadCount.getOpenUDID()).append("&");
//			}
			/***********ios6激活异常***********/
			
			callbackUrl.append("ifa=").append(adSpreadCount.getIfa());
		}

		return callbackUrl.toString();
	}
	
	private static String getDomobSign(String appid, String udid, String ma, String ifa, String oid, String key) throws NoSuchAlgorithmException {
		char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',  'e', 'f' };
		String s = appid + "," + udid + "," + ma + "," + ifa + "," + oid + "," + key;
		byte[] strTemp = s.getBytes();
		MessageDigest mdTemp = MessageDigest.getInstance("MD5");
		mdTemp.update(strTemp);
		byte[] md = mdTemp.digest();
		int j = md.length;
		char[] str = new char[j * 2];
		int k = 0;
		for (int i = 0; i < j; i++) {
			byte byte0 = md[i];
			str[(k++)] = HEX_DIGITS[(byte0 >>> 4 & 0xF)];
			str[(k++)] = HEX_DIGITS[(byte0 & 0xF)];
		}
		return new String(str);
	}

	/** 发送Http请求回调广告商 */
	private String httpConnection(String responseUrl) throws Exception {
		String lines = "";
		String sTotalString = "";
		URL url = new URL(responseUrl);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		// 进行连接，但是实际上request要在下一句的connection.getInputStream()函数中才会真正发到
		// 服务器
		// 设置超时时间（3秒）
		connection.setConnectTimeout(3000);
		connection.connect();

		// 取得输入流，并使用Reader读取
		BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));

		while ((lines = reader.readLine()) != null) {
			sTotalString += lines;
		}
		reader.close();
		connection.disconnect();
		return sTotalString;
	}
	
	/**
	 * 检查用户点击广告的时间是否是3天以内
	 * @param map
	 * @return
	 * @throws Exception 
	 */
	private Integer checkClickTime(Date clickTime) {
		Date nowTime = new Date();
		long diff = nowTime.getTime() - clickTime.getTime();
		long days = diff / (1000 * 60 * 60 * 24);

		return Integer.valueOf(String.valueOf(days));
	}
	
	/**
	 * 检查输入参数是否为null
	 * @param str
	 * @return
	 * @throws Exception 
	 */
	private String checkNull(String str) {
		return str == null ? " " : str;
	}
}
